#include "PSRAM_DMA.h"
#include "driver_system.h"
#include "driver_pmu.h"
#include "driver_psram.h"
#include "driver_spi.h"
#include "driver_gpio.h"
#include "driver_dma.h"
#include "plf.h"

static DMA_LLI_InitTypeDef Link_Channel[20];
static DMA_HandleTypeDef gc9c01_DMA_Channel;
static dma_LinkParameter_t LinkParameter;

static volatile bool dma_transfer_done = true;
static volatile bool mem_copy_dma_transfer_done = true;

DMA_HandleTypeDef MEM_COPY_DMA_Handle;

/*********************************************************************************
* function   :   PSRAM_DMA_Init  
* Description :  初始化DMA
* Input       :  
* Output      :  
* Author      :  祁鑫                  Data : 2021 4.1
**********************************************************************************/
void PSRAM_DMA_Init(void)
{

    __SYSTEM_DMA_CLK_ENABLE();
	  MEM_COPY_DMA_Handle.Channel               = DMA_Channel2;
    MEM_COPY_DMA_Handle.Init.Data_Flow        = DMA_M2M_DMAC;
    MEM_COPY_DMA_Handle.Init.Source_Inc       = DMA_ADDR_INC_INC;
    MEM_COPY_DMA_Handle.Init.Desination_Inc   = DMA_ADDR_INC_INC;
    MEM_COPY_DMA_Handle.Init.Source_Width     = DMA_TRANSFER_WIDTH_32;
    MEM_COPY_DMA_Handle.Init.Desination_Width = DMA_TRANSFER_WIDTH_32;
    dma_init(&MEM_COPY_DMA_Handle);
    DMA->Channels[MEM_COPY_DMA_Handle.Channel].CFG1.CH_PRIOR = 6;
}

/*********************************************************************************
* function   :   MEM2MEM_COPY_DMA  
* Description :  内存拷贝函数
* Input       :  
* Output      :  
* Author      :  祁鑫                  Data : 2021 4.1
**********************************************************************************/
void MEM2MEM_COPY_DMA(uint32_t pixel_count, uint8_t *src,uint8_t *dst)
{
    uint32_t i;
    uint32_t total_count = pixel_count/2; 
    uint8_t link_count = total_count / 4000;  
    if(mem_copy_dma_transfer_done == false)
    {
        return;
    }
    else
    {
        mem_copy_dma_transfer_done = false;
    }
    
    
    if(total_count % 4000)
    {
        link_count++;
    }
    for (i = 0; i < link_count; i++)
    
		{
        uint8_t all_set = (total_count <= 4000);
        
        LinkParameter.SrcAddr          = (uint32_t)&src[i*8000];
        LinkParameter.DstAddr          = (uint32_t)&dst[i*8000];
        if(all_set)
        {
            LinkParameter.NextLink     = 0;
        }
        else
        {
            LinkParameter.NextLink     = (uint32_t)&Link_Channel[i + 1];
        }
        LinkParameter.Data_Flow        = DMA_M2M_DMAC;
        //LinkParameter.Request_ID       = gc9c01_DMA_Channel.Init.Request_ID;
        LinkParameter.Source_Inc       = DMA_ADDR_INC_INC;
        LinkParameter.Desination_Inc   = DMA_ADDR_INC_INC;
        LinkParameter.Source_Width     = DMA_TRANSFER_WIDTH_32;
        LinkParameter.Desination_Width = DMA_TRANSFER_WIDTH_32;
        LinkParameter.Burst_Len        = DMA_BURST_LEN_4;
        LinkParameter.Size             = all_set ? (total_count) : 4000;
        LinkParameter.gather_enable    = 0;
        LinkParameter.scatter_enable   = 0;
        total_count -= 4000;

        dma_linked_list_init(&Link_Channel[i], &LinkParameter);
    }

        dma_linked_list_start(Link_Channel, &LinkParameter, MEM_COPY_DMA_Handle.Channel);
				while(!dma_get_tfr_Status(MEM_COPY_DMA_Handle.Channel));
				dma_clear_tfr_Status(MEM_COPY_DMA_Handle.Channel);
        mem_copy_dma_transfer_done = true;
}


uint16_t *display1=(uint16_t *)(0x22000000);
uint16_t *display2=(uint16_t *)(0x22000000+240*240*2);

void PSRAM_COPY_TEST(void)
{
 //PSRAM->PSRAM LCD 240*240
 MEM2MEM_COPY_DMA(240*240*2, (uint8_t*)display1,(uint8_t*)display2);
}